#ifndef _PACKAGE_CPP
#define _PACKAGE_CPP
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <Windows.H>
#include <ShlObj.H>
#include <Stdio.H>
#include <Stdlib.H>

#include "../Resources/Resource.H"

#include "NSWFL.H"
#include "IndexDir.H"
#include "Package.H"
#include "Entry.H"
#include "CRC32.H"
#include "Common.H"

#include "../Dialogs/MainDlg.H"
#include "../Dialogs/OpenPassDlg.H"
#include "../Dialogs/ReadingDlg.H"
#include "../Dialogs/PackingDlg.H"
#include "../Dialogs/ExtractDlg.H"

#include "../Modules/NASCCL/NASCCL.H"
#include "../Modules/LZSS/LZSS_Compress.H"
#include "../Modules/LZSS/LZSS_Uncompress.H"

#include "../Modules/Rijndael/AES.H"
#include "../Modules/Rijndael/AESOpt.H"
#include "../Modules/Rijndael/Rijndael.H"

#include "../Modules/BlowFish/BlowFish.H"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD dwPackageProgress = 0;
DWORD dwWorker_Thread_ID = 0;
HANDLE hWorker_Thread_Handle = NULL;

FILEPACKAGE AltFilePackage;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool MakePackage(LPMKPKGPARAM lpMyMkPkgParam)
{
    unsigned char *sBlockBuffer1 = NULL;
    unsigned char *sBlockBuffer2 = NULL;
    
	char Ext[255];
    char FileName[255];
    char FullFileName[MAX_PATH + 1];
    char LastDirName[MAX_PATH + 1];
    char StatusText[1024 + 1];
    char TempBuf[1024];

	DWORD BytesRead = 0;
    DWORD BytesWritten = 0;
    DWORD CompressedFileSize = 0;
    DWORD CompSeekPos = 0;
    DWORD CurrentFPointer = 0;
    DWORD DeflSize = 0;
    DWORD dwBlockSize = -1;
    DWORD FileCount = 0;
    DWORD FileSize = 0;

	FILETIME CreationTime;
    FILETIME LastWriteTime;

	HANDLE hfSource = NULL;
    HANDLE hfTarget = NULL;

	int CompressResult = 0;
    int iBufferSize = DfltBufferSize;
    int iTemp = 0;

	long Checksum1 = 0;
    long Checksum2 = 0;

	unsigned char *SourceBuf = NULL;
    unsigned char *TargetBuf = NULL;
    unsigned long FinalCRC = 0;
    unsigned long LoopCount = 0;
    unsigned short FileNameLen = 0;

    NASCCL MyNASCCL;
	BlowFishCTX MyBlowFish;
	aes_ctx MyAes_Ctx;
    FilePack MyFilePack;
	HS_LZSS_Compress MyLZSS_Compress;
	FILEPACKAGE MyFilePackage;

    memset(&MyNASCCL, 0, sizeof(MyNASCCL));
	memset(&MyFilePack, 0, sizeof(MyFilePack));
    memset(TempBuf, 0, sizeof(TempBuf));
    memset(&MyFilePackage, 0, sizeof(FILEPACKAGE));

	if(lpMyMkPkgParam->iOptions &ATTRIB_USEALTFILEPACK)
	{
		memcpy(&MyFilePackage, &AltFilePackage, sizeof(FILEPACKAGE));
	}
	else{
		MyFilePack.Initialize(&MyFilePackage);

		Set_Text(PackingActionText_hWnd, "Searching:");

		if(!MyFilePack.IndexDirectory(lpMyMkPkgParam->sSrcFolder, strlen(lpMyMkPkgParam->sSrcFolder), &MyFilePackage))
		{
			if(gdwCurrentJobType == JOB_TYPE_CANCEL)
			{
				return true;
			}
			else{
				sprintf(StatusText, "An error occured while trying to index the directory:\r\n'%s'", lpMyMkPkgParam->sSrcFolder);
				MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
				return false;
			}
		}
	}

    GetLastDirectoryInPath(lpMyMkPkgParam->sSrcFolder, LastDirName);

    Sleep(1000);

    MyNASCCL.InitializeCryptographySet(lpMyMkPkgParam->sRawKey, lpMyMkPkgParam->iRawKeyLen, CRYPTMETHOD);

	if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_COMPRESSION)
    {
        MyLZSS_Compress.SetupCompressionLevel(giCompressLevel);
    }

	if(lpMyMkPkgParam->iOptions &ATTRIB_ADDFILES)
	{
		hfTarget = CreateFile(
			lpMyMkPkgParam->sTarName,
			GENERIC_WRITE,
			0,
			NULL,
			OPEN_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL
		);
	}
	else{
		hfTarget = CreateFile(
			lpMyMkPkgParam->sTarName,
			GENERIC_WRITE,
			0,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL
		);
	}

	if(hfTarget == INVALID_HANDLE_VALUE)
    {
        sprintf(StatusText, "Failed to open write file:\r\n'%s'", lpMyMkPkgParam->sTarName);
        MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
        return false;
    }

    Checksum1 = MakeChecksum(lpMyMkPkgParam->sRawKey);
    WriteFile(hfTarget, &Checksum1, sizeof(long), &BytesWritten, NULL);

	Checksum2 = HARDCHECKSUM;
    MyNASCCL.Encode(&Checksum2, &Checksum2, sizeof(long));
    WriteFile(hfTarget, &Checksum2, sizeof(long), &BytesWritten, NULL);

	//Write the PkgAttribs
    MyNASCCL.Encode(&lpMyMkPkgParam->iPkgAttribs, &iTemp, sizeof(int));
    WriteFile(hfTarget, &iTemp, sizeof(int), &BytesWritten, NULL);

	//Write the giCryptAlgo
	MyNASCCL.Encode(&giCryptAlgo, &iTemp, sizeof(int));
    WriteFile(hfTarget, &iTemp, sizeof(int), &BytesWritten, NULL);

    MyNASCCL.Encode(&MyFilePackage.FileCount, &FileCount, sizeof(DWORD));
    WriteFile(hfTarget, &FileCount, sizeof(DWORD), &BytesWritten, NULL);

    SendMessage(PackingStatusBar_hWnd, PBM_SETRANGE, 0, (LPARAM) MAKELPARAM(0, MyFilePackage.FileCount));

    SourceBuf = (unsigned char *) calloc(iBufferSize + 1, sizeof(char));
    TargetBuf = (unsigned char *) calloc((iBufferSize + ExtraSize) + 1, sizeof(char));

    Set_Text(PackingActionText_hWnd, "Adding:");

	if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL)
	{
		char sRijndaelKey[RIJNDAEL_KEY_LEN + 1];
		HashKey(lpMyMkPkgParam->sRawKey, sRijndaelKey, lpMyMkPkgParam->iRawKeyLen, RIJNDAEL_KEY_LEN);

		memset(&MyAes_Ctx, 0, sizeof(MyAes_Ctx));
	
		aes_enc_key((unsigned char *)sRijndaelKey, RIJNDAEL_KEY_LEN, &MyAes_Ctx);
		dwBlockSize = 32;
	}

	if(giCryptAlgo == CRYPT_ALGO_BLOWFISH)
	{
		char sBlowFishKey[BLOWFISH_KEY_LEN + 1];
		HashKey(lpMyMkPkgParam->sRawKey, sBlowFishKey, lpMyMkPkgParam->iRawKeyLen, BLOWFISH_KEY_LEN);
			
		memset(&MyBlowFish, 0, sizeof(MyBlowFish));
	
		Blowfish_Init(&MyBlowFish, (unsigned char *)sBlowFishKey, BLOWFISH_KEY_LEN);
		dwBlockSize = 8; //Two DWORDS's

		sBlockBuffer1 = (unsigned char *) calloc(dwBlockSize + 1, sizeof(unsigned char));
		sBlockBuffer2 = (unsigned char *) calloc(dwBlockSize + 1, sizeof(unsigned char));
	}

	while(LoopCount < MyFilePackage.FileCount)
    {
        strcpy(FullFileName, lpMyMkPkgParam->sSrcFolder);
        strcat(FullFileName, MyFilePackage.FileNames[LoopCount]);

        if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_SAVEPATHS)
        {
            strcpy(TempBuf, LastDirName);
            strcat(TempBuf, MyFilePackage.FileNames[LoopCount]);
        }
        else{
            _splitpath(MyFilePackage.FileNames[LoopCount], NULL, NULL, FileName, Ext);
            _makepath(TempBuf, NULL, NULL, FileName, Ext);
        }

        FileNameLen = strlen(TempBuf);

        WriteFile(hfTarget, &FileNameLen, sizeof(unsigned short), &BytesWritten, NULL);
		MyNASCCL.Encode(TempBuf, TempBuf, FileNameLen);
        WriteFile(hfTarget, TempBuf, FileNameLen, &BytesWritten, NULL);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Sleep(1000);
            break;
        }

        SetStatusFileName(PackingStatusText_hWnd, MyFilePackage.FileNames[LoopCount]);

        hfSource = CreateFile(
            FullFileName,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );

        if(hfSource == INVALID_HANDLE_VALUE)
        {
            sprintf(StatusText, "Failed to open read file:\r\n'%s'", FullFileName);
            MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);

            CloseHandle(hfTarget);
            free(SourceBuf);
            free(TargetBuf);

			//Free memory for the RIJNDAEL algo.
			if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL)
			{
				free(sBlockBuffer1);
				free(sBlockBuffer2);
			}
            return false;
        }

        FileSize = GetFileSize(hfSource, NULL);
        WriteFile(hfTarget, &FileSize, sizeof(DWORD), &BytesWritten, NULL);

        CompSeekPos = SetFilePointer(hfTarget, 0, NULL, FILE_CURRENT);
        // To make room for the compressed size
        WriteFile(hfTarget, &FileSize, sizeof(DWORD), &BytesWritten, NULL);

        if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_DATETIME)
        {
            GetFileTime(hfSource, &CreationTime, NULL, &LastWriteTime);
            WriteFile(hfTarget, &CreationTime, sizeof(FILETIME), &BytesWritten, NULL);
            WriteFile(hfTarget, &LastWriteTime, sizeof(FILETIME), &BytesWritten, NULL);
        }

        if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_CRCCHECK)
        {
        	FinalCRC = 0xffffffff;
        }

        bool bCompression = true;

        do{
            ReadFile(hfSource, SourceBuf, iBufferSize, &BytesRead, NULL);

            if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_CRCCHECK)
            {
                FinalCRC = PartialCRC(FinalCRC, SourceBuf, BytesRead);
            }
			if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_COMPRESSION)
            {
        		CompressResult = MyLZSS_Compress.Compress(SourceBuf, TargetBuf, BytesRead, &DeflSize);
            }
            else CompressResult = -1;

            if(CompressResult != HS_LZSS_E_OK)
            {
                memcpy(TargetBuf, SourceBuf, BytesRead);
                DeflSize = BytesRead;
                bCompression = false;
                WriteFile(hfTarget, &bCompression, sizeof(bool), &BytesWritten, NULL);
            }
            else{
                bCompression = true;
                WriteFile(hfTarget, &bCompression, sizeof(bool), &BytesWritten, NULL);
            }

            TargetBuf[DeflSize] = '\0';

			WriteFile(hfTarget, &BytesRead, sizeof(DWORD), &BytesWritten, NULL);
			WriteFile(hfTarget, &DeflSize, sizeof(DWORD), &BytesWritten, NULL);

			if(giCryptAlgo == CRYPT_ALGO_NASCCL)
			{
				MyNASCCL.Encode(TargetBuf, TargetBuf, DeflSize);
				WriteFile(hfTarget, TargetBuf, DeflSize, &BytesWritten, NULL);
			}
			else if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL) {
				DWORD dwBlockGap = dwBlockSize - (DeflSize % dwBlockSize);

				WriteFile(hfTarget, &dwBlockGap, sizeof(DWORD), &BytesWritten, NULL);

				DWORD dwRPos = 0;
				DWORD dwWPos = 0;
				DWORD dwFill = 0;

				while(dwRPos < DeflSize)
				{
					dwWPos = 0;
					while(dwWPos < dwBlockSize && dwRPos < DeflSize)
						sBlockBuffer1[dwWPos++] = TargetBuf[dwRPos++];

					dwFill = dwWPos;
					while(dwFill < dwBlockSize)
						sBlockBuffer1[dwFill++] = '*';
				
					aes_enc_blk((unsigned char *)sBlockBuffer1, (unsigned char *)sBlockBuffer2, &MyAes_Ctx);

					WriteFile(hfTarget, sBlockBuffer2, dwFill, &BytesWritten, NULL);
				}
			}
			else if(giCryptAlgo == CRYPT_ALGO_BLOWFISH) {
				DWORD dwBlockGap = dwBlockSize - (DeflSize % dwBlockSize);
				DWORD dwL = 0;
				DWORD dwR = 0;

				WriteFile(hfTarget, &dwBlockGap, sizeof(DWORD), &BytesWritten, NULL);

				DWORD dwRPos = 0;
				DWORD dwWPos = 0;
				DWORD dwFill = 0;

				while(dwRPos < DeflSize)
				{
					dwWPos = 0;
				    while(dwWPos < sizeof(DWORD) && dwRPos < DeflSize)
						((char *)&dwL)[dwWPos++] = TargetBuf[dwRPos++];

					dwFill = dwWPos;
					while(dwFill < sizeof(DWORD))
						((char *)&dwL)[dwFill++] = '0';
				
					dwWPos = 0;
					while(dwWPos < sizeof(DWORD) && dwRPos < DeflSize)
						((char *)&dwR)[dwWPos++] = TargetBuf[dwRPos++];

					dwFill = dwWPos;
					while(dwFill < sizeof(DWORD))
						((char *)&dwR)[dwFill++] = '0';
				
					Blowfish_Encrypt(&MyBlowFish, &dwL, &dwR);

					WriteFile(hfTarget, &dwL, sizeof(DWORD), &BytesWritten, NULL);
					WriteFile(hfTarget, &dwR, sizeof(DWORD), &BytesWritten, NULL);
				}
			}
        } while(BytesRead == iBufferSize);

        if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_CRCCHECK)
        {
            FinalCRC = (FinalCRC ^ 0xffffffff);
        }

        CurrentFPointer = SetFilePointer(hfTarget, 0, NULL, FILE_CURRENT);
        CompressedFileSize = ((CurrentFPointer - CompSeekPos) - sizeof(DWORD));
        SetFilePointer(hfTarget, CompSeekPos, NULL, FILE_BEGIN);
        WriteFile(hfTarget, &CompressedFileSize, sizeof(DWORD), &BytesWritten, NULL);
        SetFilePointer(hfTarget, CurrentFPointer, NULL, FILE_BEGIN);

        if(lpMyMkPkgParam->iPkgAttribs &ATTRIB_CRCCHECK)
        {
            WriteFile(hfTarget, &FinalCRC, sizeof(DWORD), &BytesWritten, NULL);
        }

        CloseHandle(hfSource);

        LoopCount++;
        dwPackageProgress = LoopCount;
	}

    free(SourceBuf);
    free(TargetBuf);

	//Free memory for the RIJNDAEL algo.
	if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL)
	{
		free(sBlockBuffer1);
		free(sBlockBuffer2);
	}

	MyFilePack.FreeMemory(&MyFilePackage);

    CloseHandle(hfTarget);

    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool BreakPackage(char *SrcName, char *TarFolder, char *RawKey, int RawKeyLen)
{
    char *sBlockBuffer1 = NULL;
    char *sBlockBuffer2 = NULL;

	char FullFileName[256];
    char PartFileName[256];
    char StatusText[255 + 1];
    char TempBuf[1024];

	DWORD BytesRead = 0;
    DWORD BytesWritten = 0;
    DWORD CompressedFileSize = 0;
    DWORD DeflSize = 0;
    DWORD dwBlockSize = -1;
    DWORD FileCount = 0;
    DWORD FileSize = 0;
    DWORD InflSize = 0;
    DWORD OrigSize = 0;

	FILETIME CreationTime;
    FILETIME LastWriteTime;

	HANDLE hfSource = NULL;
    HANDLE hfTarget = NULL;

	int CompressResult = 0;
    int iBufferSize = DfltBufferSize;
    int iTemp = 0;
    int PkgAttribs = 0;

	long Checksum = 0;
    long ReadChecksum1 = 0;
    long ReadChecksum2 = 0;

	unsigned char *SourceBuf = NULL;
    unsigned char *TargetBuf = NULL;

	unsigned long FinalCRC = 0;
    unsigned long LoopCount = 0;
    unsigned long ReadCRC = 0;

	unsigned short FileNameLen = 0;

    NASCCL MyNASCCL;
	BlowFishCTX MyBlowFish;
	aes_ctx MyAes_Ctx;
	HS_LZSS_Uncompress MyLZSS_Uncompress;

    memset(&MyNASCCL, 0, sizeof(MyNASCCL));
    memset(TempBuf, 0, sizeof(TempBuf));

	MyNASCCL.InitializeCryptographySet(RawKey, RawKeyLen, CRYPTMETHOD);

    Checksum = MakeChecksum(RawKey);

    hfSource = CreateFile(
        SrcName,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );

    if(hfSource == INVALID_HANDLE_VALUE)
    {
        sprintf(StatusText, "Failed to open read file:\r\n'%s'.", SrcName);
        MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
        return false;
    }

    ReadFile(hfSource, &ReadChecksum1, sizeof(long), &BytesRead, NULL);
    ReadFile(hfSource, &ReadChecksum2, sizeof(long), &BytesRead, NULL);
    MyNASCCL.Decode(&ReadChecksum2, &ReadChecksum2, sizeof(long));

    if(ReadChecksum1 != Checksum || ReadChecksum2 != HARDCHECKSUM)
    {
        MessageBox(PackingDialog_hWnd, "Wrong key, Can't decrypt.", gsTitleCaption, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL);
        CloseHandle(hfSource);
        return false;
    }

	//Read the PkgAttribs
    ReadFile(hfSource, &PkgAttribs, sizeof(int), &BytesRead, NULL);
    MyNASCCL.Decode(&PkgAttribs, &PkgAttribs, sizeof(int));

	//Read the giCryptAlgo
	ReadFile(hfSource, &giCryptAlgo, sizeof(int), &BytesRead, NULL);
    MyNASCCL.Decode(&giCryptAlgo, &giCryptAlgo, sizeof(int));

	ReadFile(hfSource, &FileCount, sizeof(DWORD), &BytesRead, NULL);
    MyNASCCL.Decode(&FileCount, &FileCount, sizeof(DWORD));
	if(gdwCurrentJobType == JOB_TYPE_EXTRACTSEL)
	{
		SendMessage(PackingStatusBar_hWnd, PBM_SETRANGE, 0, (LPARAM) MAKELPARAM(0, ListView_GetSelectedCount(FileList_hWnd)));
	}
	else SendMessage(PackingStatusBar_hWnd, PBM_SETRANGE, 0, (LPARAM) MAKELPARAM(0, FileCount));

    dwPackageProgress = 0;

    SourceBuf = (unsigned char *) calloc((iBufferSize + ExtraSize) + 1, sizeof(char));
    TargetBuf = (unsigned char *) calloc((iBufferSize + ExtraSize) + 1, sizeof(char));

	if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL)
	{
		char sRijndaelKey[RIJNDAEL_KEY_LEN + 1];
		HashKey(RawKey, sRijndaelKey, RawKeyLen, RIJNDAEL_KEY_LEN);

		memset(&MyAes_Ctx, 0, sizeof(MyAes_Ctx));
	
		aes_enc_key((unsigned char *)sRijndaelKey, RIJNDAEL_KEY_LEN, &MyAes_Ctx);
		dwBlockSize = 32;

		sBlockBuffer1 = (char *) calloc(dwBlockSize + 1, sizeof(char));
		sBlockBuffer2 = (char *) calloc(dwBlockSize + 1, sizeof(char));
	}

	if(giCryptAlgo == CRYPT_ALGO_BLOWFISH)
	{
		char sBlowFishKey[BLOWFISH_KEY_LEN + 1];
		HashKey(RawKey, sBlowFishKey, RawKeyLen, BLOWFISH_KEY_LEN);
			
		memset(&MyBlowFish, 0, sizeof(MyBlowFish));
	
		Blowfish_Init(&MyBlowFish, (unsigned char *)sBlowFishKey, BLOWFISH_KEY_LEN);
		dwBlockSize = 8;
	}

	//--------------------------------------------------------------------------------

    Set_Text(PackingActionText_hWnd, "Extracting:");

    int iLVItemPos = -1;

	DWORD dwFilePos = 0;

	do{

        if(gdwCurrentJobType == JOB_TYPE_EXTRACTSEL)
        {
			DWORD dwTempfPos = 0;

			while((iLVItemPos = ListView_GetNextItem(FileList_hWnd, iLVItemPos, LVNI_SELECTED)) != -1)
            {
                ListView_GetItemText(FileList_hWnd, iLVItemPos, 9, TempBuf, 255);
	            SetFilePointer(hfSource, atol(TempBuf), NULL, FILE_BEGIN);
				break;
            }

			if(iLVItemPos == -1)
			{
				break;
			}
		}
		
	    ReadFile(hfSource, &FileNameLen, sizeof(unsigned short), &BytesRead, NULL);
		if(BytesRead == 0)
		{
			//This is where this loop ends.
			break;
		}

		if(FileNameLen <= 0 || FileNameLen > 255)
        {
            sprintf(StatusText, "Corrupt data file detected. Error code: %X", FileNameLen);
            MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
            break;
        }

        ReadFile(hfSource, PartFileName, FileNameLen, &BytesRead, NULL);
        MyNASCCL.Decode(PartFileName, PartFileName, FileNameLen);
    	PartFileName[FileNameLen] = '\0';
        ReadFile(hfSource, &FileSize, sizeof(DWORD), &BytesRead, NULL);
        ReadFile(hfSource, &CompressedFileSize, sizeof(DWORD), &BytesRead, NULL);

        if(PkgAttribs &ATTRIB_DATETIME)
        {
            ReadFile(hfSource, &CreationTime, sizeof(FILETIME), &BytesRead, NULL);
            ReadFile(hfSource, &LastWriteTime, sizeof(FILETIME), &BytesRead, NULL);
        }

        strcpy(FullFileName, TarFolder);
        strcat(FullFileName, PartFileName);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Sleep(1000);
            break;
        }

        SetStatusFileName(PackingStatusText_hWnd, PartFileName);

        CreateFolderStructure(FullFileName);

        hfTarget = CreateFile(
            FullFileName,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );

        if(PkgAttribs &ATTRIB_CRCCHECK)
        {
        	FinalCRC = 0xffffffff;
        }

        bool bCompression = true;
		DWORD dwBlockGap = 0;
		DWORD dwAdjustedSize = 0;
		
		do{
            ReadFile(hfSource, &bCompression, sizeof(bool), &BytesRead, NULL);
            ReadFile(hfSource, &OrigSize, sizeof(DWORD), &BytesRead, NULL);
            ReadFile(hfSource, &DeflSize, sizeof(DWORD), &BytesRead, NULL);

			if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL || giCryptAlgo == CRYPT_ALGO_BLOWFISH)
			{
				ReadFile(hfSource, &dwBlockGap, sizeof(DWORD), &BytesRead, NULL);
				if(dwBlockGap == dwBlockSize)
				{
					dwBlockGap = 0;
				}
			}

			dwAdjustedSize = (DeflSize + dwBlockGap);

			ReadFile(hfSource, SourceBuf, dwAdjustedSize, &BytesRead, NULL);

            InflSize = (iBufferSize + ExtraSize);

			if(giCryptAlgo == CRYPT_ALGO_NASCCL)
			{
				MyNASCCL.Decode(SourceBuf, SourceBuf, DeflSize);
			}
			else if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL){
				DWORD dwRPos = 0;
				DWORD dwWPos = 0;

				DWORD dwCypRPos = 0;
				DWORD dwCypWPos = 0;

				while(dwRPos < dwAdjustedSize)
				{
					dwWPos = 0;
					while(dwWPos < dwBlockSize)
						sBlockBuffer1[dwWPos++] = SourceBuf[dwRPos++];

					aes_dec_blk((unsigned char *)sBlockBuffer1, (unsigned char *)sBlockBuffer2, &MyAes_Ctx);

					dwCypRPos = 0;
					while(dwCypRPos < dwWPos)					
						SourceBuf[dwCypWPos++] = sBlockBuffer2[dwCypRPos++];
				}
				
				SourceBuf[dwCypWPos - dwBlockGap] = '\0';
				BytesRead = (BytesRead - dwBlockGap);
			}
			else if(giCryptAlgo == CRYPT_ALGO_BLOWFISH) {
				DWORD dwL = 0;
				DWORD dwR = 0;

				DWORD dwRPos = 0;
				DWORD dwWPos = 0;

				DWORD dwCypRPos = 0;
				DWORD dwCypWPos = 0;

				while(dwRPos < dwAdjustedSize)
				{
					dwWPos = 0;
					while(dwWPos < sizeof(DWORD))
						((char *)&dwL)[dwWPos++] = SourceBuf[dwRPos++];

					dwWPos = 0;
					while(dwWPos < sizeof(DWORD))
						((char *)&dwR)[dwWPos++] = SourceBuf[dwRPos++];

					Blowfish_Decrypt(&MyBlowFish, &dwL, &dwR);

					dwCypRPos = 0;
					while(dwCypRPos < sizeof(DWORD))					
						SourceBuf[dwCypWPos++] = ((char *)&dwL)[dwCypRPos++];

					dwCypRPos = 0;
					while(dwCypRPos < sizeof(DWORD))					
						SourceBuf[dwCypWPos++] = ((char *)&dwR)[dwCypRPos++];
				}
				
				SourceBuf[dwCypWPos - dwBlockGap] = '\0';
				BytesRead = (BytesRead - dwBlockGap);
			}

			if(bCompression && (PkgAttribs &ATTRIB_COMPRESSION))
            {
        		CompressResult = MyLZSS_Uncompress.GetUncompressedSize(SourceBuf, &InflSize);
                MyLZSS_Uncompress.Uncompress(SourceBuf, TargetBuf);
                if(PkgAttribs &ATTRIB_CRCCHECK)
                {
                    FinalCRC = PartialCRC(FinalCRC, TargetBuf, InflSize);
                }
				WriteFile(hfTarget, TargetBuf, InflSize, &BytesWritten, NULL);
            }
            else {
                if(PkgAttribs &ATTRIB_CRCCHECK)
                {
                    FinalCRC = PartialCRC(FinalCRC, SourceBuf, BytesRead);
                }
				WriteFile(hfTarget, SourceBuf, BytesRead, &BytesWritten, NULL);
            }
        } while(OrigSize == iBufferSize);

        if(PkgAttribs &ATTRIB_CRCCHECK)
        {
            FinalCRC = (FinalCRC ^ 0xffffffff);
            ReadFile(hfSource, &ReadCRC, sizeof(unsigned long), &BytesRead, NULL);

            if(FinalCRC != ReadCRC)
            {
                sprintf(StatusText, "Bad CRC %X should be %X\r\n%s", FinalCRC, ReadCRC, PartFileName);
                MessageBox(PackingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
                break;
            }
        }

        if(PkgAttribs &ATTRIB_DATETIME)
        {
            SetFileTime(hfTarget, &CreationTime, NULL, &LastWriteTime);
        }

        CloseHandle(hfTarget);

        //ReadFile(hfSource, &FileNameLen, sizeof(unsigned short), &BytesRead, NULL);
        dwPackageProgress++;

    } while(BytesRead != 0);

    //--------------------------------------------------------------------------------

    free(SourceBuf);
    free(TargetBuf);
	
	//Free memory for the RIJNDAEL algo.
	if(giCryptAlgo == CRYPT_ALGO_RIJNDAEL)
	{
		free(sBlockBuffer1);
		free(sBlockBuffer2);
	}

    CloseHandle(hfSource);

    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool PopGrid(char *SrcName, char *RawKey, int RawKeyLen)
{
    char PartFileName[256];
    char StatusText[512];
    char TempBuf[128];
    char TempBuf0[128];
    char TempBuf1[128];

	double TotalFileSizes = 0;

	DWORD BytesRead = 0;
    DWORD CompressedFileSize = 0;
    DWORD dwFilePosition = 0;
    DWORD FileCount = 0;
    DWORD FileCountLoop = 0;
    DWORD FileSize = 0;

	FILETIME CreationTime;
    FILETIME LastWriteTime;

	HANDLE hfSource = NULL;

	int PkgAttribs = 0;

	long Checksum = 0;
    long ReadChecksum1 = 0;
    long ReadChecksum2 = 0;

	unsigned long ReadCRC = 0;
    unsigned short FileNameLen = 0;

    NASCCL MyNASCCL;
    LV_ITEM MyLVItem;

    memset(&MyLVItem, 0, sizeof(MyLVItem));
    memset(&MyNASCCL, 0, sizeof(MyNASCCL));
    memset(TempBuf, 0, sizeof(TempBuf));

    ImageList_RemoveAll(LV_MainDlgImageList);

    MyNASCCL.InitializeCryptographySet(RawKey, RawKeyLen, CRYPTMETHOD);

    Checksum = MakeChecksum(RawKey);

    hfSource = CreateFile(
        SrcName,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );

    if(hfSource == INVALID_HANDLE_VALUE)
    {
        sprintf(StatusText, "Failed to open read file:\r\n'%s'.", SrcName);
        MessageBox(ReadingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
        return false;
    }

    ReadFile(hfSource, &ReadChecksum1, sizeof(long), &BytesRead, NULL);
    ReadFile(hfSource, &ReadChecksum2, sizeof(long), &BytesRead, NULL);
    MyNASCCL.Decode(&ReadChecksum2, &ReadChecksum2, sizeof(long));

    if(ReadChecksum1 != Checksum || ReadChecksum2 != HARDCHECKSUM)
    {
        MessageBox(ReadingDialog_hWnd, "Wrong key, Can't decrypt.", gsTitleCaption, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL);
        CloseHandle(hfSource);
        return false;
    }

	//Read the PkgAttribs
    ReadFile(hfSource, &PkgAttribs, sizeof(int), &BytesRead, NULL);
    MyNASCCL.Decode(&PkgAttribs, &PkgAttribs, sizeof(int));

	//Read the giCryptAlgo
	ReadFile(hfSource, &giCryptAlgo, sizeof(int), &BytesRead, NULL);
    MyNASCCL.Decode(&giCryptAlgo, &giCryptAlgo, sizeof(int));

	ReadFile(hfSource, &FileCount, sizeof(DWORD), &BytesRead, NULL);
    MyNASCCL.Decode(&FileCount, &FileCount, sizeof(DWORD));
    SendMessage(ReadingStatusBar_hWnd, PBM_SETRANGE, 0, (LPARAM) MAKELPARAM(0, FileCount));

    //--------------------------------------------------------------------------------

	//dwFilePosition = SetFilePointer(hfSource, NULL, NULL, FILE_CURRENT);
	//ReadFile(hfSource, &FileNameLen, sizeof(unsigned short), &BytesRead, NULL);

    HICON MyIcon = NULL;

    int IconIndexCount = 0;
    DBGICONLIST *MyIcoList;
    MyIcoList = (DBGICONLIST *) calloc(sizeof(DBGICONLIST), FileCount + 1);

    MyIcon = LoadIcon(ghAppInstance, MAKEINTRESOURCE(IDI_UNKNOWN));
    ImageList_AddIcon(LV_MainDlgImageList, MyIcon);
    DestroyIcon(MyIcon);
    DeleteObject(MyIcon);

/*
    strcpy(MyIcoList[IconIndexCount].Ext, ".exe");
    strcpy(MyIcoList[IconIndexCount].Descr, "Application File");
    MyIcoList[IconIndexCount].Index = IconIndexCount;
    IconIndexCount++;
*/

    do {
		dwFilePosition = SetFilePointer(hfSource, NULL, NULL, FILE_CURRENT);

		ReadFile(hfSource, &FileNameLen, sizeof(unsigned short), &BytesRead, NULL);

		if(BytesRead == 0)
		{
			//This is where this loop ends.
			break;
		}

		if(FileNameLen <= 0 || FileNameLen > 255)
        {
            sprintf(StatusText, "Corrupt data file detected. Error code: %X", FileNameLen);
            MessageBox(ReadingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);

            return false;
        }

		ReadFile(hfSource, PartFileName, FileNameLen, &BytesRead, NULL);
        MyNASCCL.Decode(PartFileName, PartFileName, FileNameLen);
    	PartFileName[FileNameLen] = '\0';
        ReadFile(hfSource, &FileSize, sizeof(DWORD), &BytesRead, NULL);

        TotalFileSizes = (TotalFileSizes + (((double)FileSize) / 1024));

        ReadFile(hfSource, &CompressedFileSize, sizeof(DWORD), &BytesRead, NULL);

        if(PkgAttribs &ATTRIB_DATETIME)
		{
			ReadFile(hfSource, &CreationTime, sizeof(FILETIME), &BytesRead, NULL);
			ReadFile(hfSource, &LastWriteTime, sizeof(FILETIME), &BytesRead, NULL);
			SetFilePointer(hfSource, CompressedFileSize-16, NULL, FILE_CURRENT);
		}
		else SetFilePointer(hfSource, CompressedFileSize, NULL, FILE_CURRENT);

		if(PkgAttribs &ATTRIB_CRCCHECK)
        {
            ReadFile(hfSource, &ReadCRC, sizeof(unsigned long), &BytesRead, NULL);
        }

        char Directory[255];
        char FileName[255];
        char Ext[255];
        _splitpath(PartFileName, NULL, Directory, FileName, Ext);

		int ImageIndex = -1;

        char Descr[255 + 1];

        int IconSCount = 0;
        while(IconSCount < IconIndexCount)
        {
            if( strcmpi(MyIcoList[IconSCount].Ext, Ext) == 0)
            {
                ImageIndex = MyIcoList[IconSCount].Index;
                strcpy(Descr, MyIcoList[IconSCount].Descr);
				break;
            }
            IconSCount++;
        }

		if(ImageIndex == -1)
        {
    		char IconFile[255 + 1];
    		int IconIndex = 0;

    		if(GetIconForExt(Ext, IconFile, &IconIndex, Descr))
            {
                if(strlen(IconFile) > 0)
                {
                    MyIcon = NULL;
					ExtractIconEx(IconFile, IconIndex, NULL, &MyIcon, 1);
                    if(MyIcon)
                    {
                        int xIndex = ImageList_AddIcon(LV_MainDlgImageList, MyIcon);

						if(xIndex != -1)
                        {
                            DestroyIcon(MyIcon);
                            DeleteObject(MyIcon);

                            AllocIconList(&MyIcoList[IconSCount], strlen(Ext), strlen(Descr));

                            strcpy(MyIcoList[IconSCount].Ext, Ext);
                            strcpy(MyIcoList[IconSCount].Descr, Descr);
							MyIcoList[IconSCount].Index = xIndex;

                            ImageIndex = xIndex;

                            IconIndexCount++;
                        }
                    }
                }
            }
        }

        if(ImageIndex == -1)
        {
			sprintf(Descr, "%s File", strupr(Ext));
			ImageIndex = 0;
		}

        sprintf(TempBuf, "%s%s", FileName, Ext);
        MyLVItem.pszText  = TempBuf;
        if(PkgAttribs &ATTRIB_DATETIME)
        {
            MyLVItem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
            MyLVItem.lParam = (LPARAM) LastWriteTime.dwHighDateTime;
        }
        else MyLVItem.mask = LVIF_TEXT|LVIF_IMAGE;
        MyLVItem.iImage   = ImageIndex;
        MyLVItem.iSubItem = 0;
        ListView_InsertItem(FileList_hWnd, &MyLVItem);

        MyLVItem.pszText  = Descr; // Type
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 1;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        if(PkgAttribs &ATTRIB_DATETIME)
        {
            sprintf(TempBuf, "%x", ReadCRC);

            char TimeTemp[64];
            char DateTemp[64];

            SYSTEMTIME MyST;
            FILETIME lFT;
            FileTimeToLocalFileTime(&LastWriteTime, &lFT);
            if(FileTimeToSystemTime(&lFT, &MyST))
            {
                GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &MyST, NULL, TimeTemp, 64);
                GetDateFormat(NULL, NULL, &MyST, "MM-dd-yyyy", DateTemp, 64);
                sprintf(TempBuf, "%s %s", DateTemp, TimeTemp);
            }
            else strcpy(TempBuf, "(n/a)");
        }
        else strcpy(TempBuf, "(n/a)");

        MyLVItem.pszText  = TempBuf; // Modified
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 2;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        sprintf(TempBuf, "%d", FileSize);
        MyLVItem.pszText  = FormatiString(TempBuf0, TempBuf); // Size
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 3;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        if(PkgAttribs &ATTRIB_COMPRESSION)
        {
            if(CompressedFileSize != 0 && FileSize != 0 && FileSize > CompressedFileSize)
            {
                float fCompressedFileSize = (float) CompressedFileSize;
                float fFileSize = (float) FileSize;
                float Ratio = 100 - ((fCompressedFileSize/fFileSize) * 100);
                sprintf(TempBuf, "%.2f%%", Ratio);
            }
            else strcpy(TempBuf, "0.00%");
        }
        else strcpy(TempBuf, "(n/a)");
        MyLVItem.pszText  = TempBuf; // Ratio
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 4;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        sprintf(TempBuf, "%d", CompressedFileSize);
        MyLVItem.pszText  = FormatiString(TempBuf0, TempBuf); // Packed
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 5;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        if(PkgAttribs &ATTRIB_CRCCHECK)
        {
            sprintf(TempBuf, "%x", ReadCRC);
        }
        else strcpy(TempBuf, "(n/a)");
        MyLVItem.pszText  = TempBuf; // CRC
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 6;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        if(PkgAttribs &ATTRIB_ATTRIBUTES)
        {
            strcpy(TempBuf, "A");
        }
        else strcpy(TempBuf, "(n/a)");
        MyLVItem.pszText  = TempBuf; // Attributes
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 7;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        if(PkgAttribs &ATTRIB_SAVEPATHS)
        {
            strcpy(TempBuf, Directory);
        }
        else strcpy(TempBuf, "(n/a)");
        MyLVItem.pszText  = TempBuf; // Path
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 8;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        sprintf(TempBuf, "%d", dwFilePosition);
        MyLVItem.pszText  = TempBuf; // Position
        MyLVItem.mask     = LVIF_TEXT;
        MyLVItem.iSubItem = 9;
        ListView_SetItem(FileList_hWnd, &MyLVItem);

        //dwFilePosition = SetFilePointer(hfSource, NULL, NULL, FILE_CURRENT);

		//ReadFile(hfSource, &FileNameLen, sizeof(unsigned short), &BytesRead, NULL);

        FileCountLoop++;
        dwPackageProgress = FileCountLoop;

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Sleep(1000);
            break;
        }
    } while(BytesRead != 0 && !(FileNameLen <= 0 || FileNameLen > 255));

    CloseHandle(hfSource);


    sprintf(TempBuf, "%d", FileCount);
    FormatiString(TempBuf0, TempBuf);

    sprintf(TempBuf, "%.0f", TotalFileSizes);
    FormatiString(TempBuf1, TempBuf);

    sprintf(StatusText, "Total %s files, %s KB", TempBuf0, TempBuf1);
    SendMessage(StatusBar_hWnd, (UINT)SB_SETTEXT, (WPARAM)1, (LPARAM)StatusText);
    SendMessage(StatusBar_hWnd, (UINT)SB_SETTEXT, (WPARAM)0, (LPARAM)"Ready");

    // Free the icon search list.
    int IconSCount = 0;
    while(IconSCount < IconIndexCount)
    {
        FreeIconList(&MyIcoList[IconSCount]);
		IconSCount++;
	}

    if(FileNameLen <= 0 || FileNameLen > 255)
    {
        sprintf(StatusText, "Corrupt data file detected. Error code: %X", FileNameLen);
        MessageBox(ReadingDialog_hWnd, StatusText, gsTitleCaption, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);

        return false;
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD WINAPI ExtractEntireArchive_Worker_Thread(LPVOID xData)
{
    char *CmdLine = (char *) xData;

    while(!IsWindowVisible(PackingDialog_hWnd))
    {
        Sleep(1);
    }

    if(IsWindow(MainDialog_hWnd))
    {
        SetForegroundWindow(MainDialog_hWnd);
    }

    Set_Text(PackingActionText_hWnd, "Starting process...");

    Sleep(100);

    if(BreakPackage(CmdLine, gsExtractLocation, gsPassword, strlen(gsPassword)))
    {
        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(PackingActionText_hWnd, "Cancelled.");
            Set_Text(PackingStatusText_hWnd, "");
            Sleep(1000);
        }
        else{
            Set_Text(PackingActionText_hWnd, "Done.");
            Set_Text(PackingStatusText_hWnd, "");
            Sleep(100);
        }

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;
        EndDialog(PackingDialog_hWnd, 1);

        return 0;
    }
    else{
        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(PackingActionText_hWnd, "Cancelled.");
            Set_Text(PackingStatusText_hWnd, "");
        }

        Sleep(1000);

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;
        EndDialog(PackingDialog_hWnd, 1);

        return 0;
    }

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD WINAPI ViewExisting_Worker_Thread(LPVOID xData)
{
    char *CmdLine = (char *) xData;

//    while(!IsWindowVisible(ReadingDialog_hWnd))
    {
        Sleep(1);
    }

    if(IsWindow(MainDialog_hWnd))
    {
        SetForegroundWindow(MainDialog_hWnd);
    }

    Set_Text(ReadingStatusText_hWnd, "Please wait... Decrypting the archive.");
    Sleep(100);

    if(PopGrid(CmdLine, gsPassword, strlen(gsPassword)))
    {
        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(ReadingStatusText_hWnd, "Cancelled.");
            Sleep(1000);
            dwPackageProgress = 0;
            gdwCurrentJobType = 0;
            EndDialog(ReadingDialog_hWnd, 0);
        }
        else{
            Set_Text(ReadingStatusText_hWnd, "Done.");
            Sleep(250);
            dwPackageProgress = 0;
            gdwCurrentJobType = 0;
            EndDialog(ReadingDialog_hWnd, 1);
        }

        return 0;
    }
    else{
        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(ReadingStatusText_hWnd, "Cancelled.");
        }

        Sleep(1000);
        dwPackageProgress = 0;
        gdwCurrentJobType = 0;
        EndDialog(ReadingDialog_hWnd, 0);

        return 0;
    }

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD WINAPI CreateNewDirArchive_Worker_Thread(LPVOID xData)
{
    char *CmdLine = (char *) xData;

    while(!IsWindowVisible(PackingDialog_hWnd))
    {
        Sleep(1);
    }

    if(IsWindow(MainDialog_hWnd))
    {
        SetForegroundWindow(MainDialog_hWnd);
    }

    Set_Text(PackingStatusText_hWnd, "Please wait...");
    Sleep(100);

    MKPKGPARAM MyMkPkgParam;
	memset(&MyMkPkgParam, 0, sizeof(MyMkPkgParam));
	MyMkPkgParam.sSrcFolder = CmdLine;
	MyMkPkgParam.sTarName = gsWorkingOutput;
	MyMkPkgParam.sRawKey = gsPassword;
	MyMkPkgParam.iRawKeyLen = strlen(gsPassword);
	MyMkPkgParam.iPkgAttribs = giPkgAttribs;
	MyMkPkgParam.iOptions = 0;

	if(MakePackage(&MyMkPkgParam))
    {
        strcpy(gsArchiveName, gsWorkingOutput);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(PackingStatusText_hWnd, "Cancelled.");
            Sleep(1000);
            EndDialog(PackingDialog_hWnd, 0);
            DeleteFile(gsWorkingOutput);
        }
        else{
            Set_Text(PackingStatusText_hWnd, "Done.");
            Sleep(1000);
            EndDialog(PackingDialog_hWnd, 1);
        }

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;

        return 0;
    }
    else{
        DeleteFile(gsWorkingOutput);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
            Set_Text(PackingStatusText_hWnd, "Cancelled.");

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;

        Sleep(1000);
        EndDialog(PackingDialog_hWnd, 0);

        return 0;
    }

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD WINAPI CreateFileArchive_Worker_Thread(LPVOID xData)
{
	char *CmdLine = (char *) xData;

    while(!IsWindowVisible(PackingDialog_hWnd))
    {
        Sleep(1);
    }

    if(IsWindow(MainDialog_hWnd))
    {
        SetForegroundWindow(MainDialog_hWnd);
    }

    Set_Text(PackingStatusText_hWnd, "Please wait...");
    Sleep(100);

    MKPKGPARAM MyMkPkgParam;
	memset(&MyMkPkgParam, 0, sizeof(MyMkPkgParam));
	MyMkPkgParam.sSrcFolder = CmdLine;
	MyMkPkgParam.sTarName = gsWorkingOutput;
	MyMkPkgParam.sRawKey = gsPassword;
	MyMkPkgParam.iRawKeyLen = strlen(gsPassword);
	MyMkPkgParam.iPkgAttribs = giPkgAttribs;
	MyMkPkgParam.iOptions = ATTRIB_USEALTFILEPACK;

	if(MakePackage(&MyMkPkgParam))
    {
        strcpy(gsArchiveName, gsWorkingOutput);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
        {
            Set_Text(PackingStatusText_hWnd, "Cancelled.");
            Sleep(1000);
            EndDialog(PackingDialog_hWnd, 0);
            DeleteFile(gsWorkingOutput);
        }
        else{
            Set_Text(PackingStatusText_hWnd, "Done.");
            Sleep(1000);
            EndDialog(PackingDialog_hWnd, 1);
        }

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;

        return 0;
    }
    else{
        DeleteFile(gsWorkingOutput);

        if(gdwCurrentJobType == JOB_TYPE_CANCEL)
            Set_Text(PackingStatusText_hWnd, "Cancelled.");

        dwPackageProgress = 0;
        gdwCurrentJobType = 0;

        Sleep(1000);
        EndDialog(PackingDialog_hWnd, 0);

        return 0;
    }

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
